#include <assert.h>
#include <ctype.h>
#include <locale.h>
#include <errno.h>
#include <float.h>
#include <inttypes.h>
#include <limits.h>
#include <math.h>
#include <setjmp.h>
#include <signal.h>
#include <stdarg.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define ROWS 3
#define COLS 2


void passing_2d_array_rows_cols_to_funcion(int (*array)[COLS], int rows, int cols)
{
    printf("***** passing_2d_array_rows_cols_to_funcion *****\n");
    int r = rows;
    int c = cols;
    int i, j;
    for ( i = 0; i < r; i++ )
    {
        for ( j = 0; j < c; j++ )
        {
            printf("array[%d][%d] = %d\n", i, j, array[i][j]);
        }
    }
}


void passing_2d_array_rows_cols_to_funcion_checks_ommitted(int (*array)[], int rows, int cols)
{
    printf("***** passing_2d_array_rows_cols_to_funcion_checks_ommitted *****\n");
    int i, j;
    int r, c;
    r = rows;
    c = cols;
    printf("\nPrint array with %d rows and %d columns\n", rows, cols);
    for ( i = 0; i < c; i++)
    {
        for ( j = 0; j < c; j++ )
        {
            printf("array[%d][%d] = %d\n", i, j, *( (*array) + ( i * cols + j)));
        }
    }
}


void passing_2d_array_and_rows_to_funcion(int (*array)[COLS], int rows)
{
    printf("***** passing_2d_arrayand_rows_to_funcion *****\n");
    int i, j;
    int r, c;
    r = rows;
    c = (int)( sizeof(array[0]) / sizeof(array[0][0]) );
    for ( i = 0; i < r; i++ )
    {
        for ( j = 0; j < c; j++ )
        {
            printf("array[%d][%d] = %d\n", i, j, array[i][j]);
        }
    }
}

void passing_2d_array_and_rows_to_funcion_order(int rows, int cols, int **array)
{
    printf("***** passing_2d_array_and_rows_to_funcion_order *****\n");
    int i, j;
    int r, c;


    r = rows;
    c = cols;

    printf("Print array with %d rows and %d columns\n", rows, cols);
    for ( i = 0; i < r; i++)
    {
        for ( j = 0; j < c; j++)
        {
            printf("array[%d][%d] = %d\n", i, j, array[i][j]);
        }
    }
}


void using_flat_array_as_2d_array(double *matrix, int width, int height)
{
    printf("***** using_flat_array_as_2d_array *****\n");
    int w, h;

    for ( h = 0; h < height; h++ )
    {

        for ( w = 0; w < width; w++ )
        {
            matrix[h * width + w] *= 2.0;
            printf("  %f  ", matrix[h * width + w] );
        }
        printf("\n");
    }
    printf("matrix[%d * %d + %d] : %f\n", h-1, width, w-1, matrix[(h - 1) * width + (w - 1)] );
}


int main(void)
{
    int array_2d[ROWS][COLS] = { {1, 2}, {3, 4}, {5, 5}};
    int rows = ROWS;
    int cols = COLS;
    passing_2d_array_rows_cols_to_funcion(array_2d, rows, cols);
    passing_2d_array_rows_cols_to_funcion_checks_ommitted(array_2d, rows, cols);
    passing_2d_array_and_rows_to_funcion(array_2d, rows);

    int *arry_1d[ROWS];
    for ( int i = 0; i < rows; i++ )
    {
        arry_1d[i] = array_2d[i];
    }
    passing_2d_array_and_rows_to_funcion_order(rows, cols, arry_1d);

    int height = 3; // row
    int width = 3; // column
    /* create 2D array with dimensions determined at runtime */
    double *matrix = malloc(width * height * sizeof(double));
    /* initialise it (for the sake of illustration we want 1.0 on the diagonal) */
    int x, y;
    for (y = 0; y < height; y++)
    {
        for (x = 0; x < width; x++)
        {
            if (x == y)
                matrix[y * width + x] = 1.0;
            else
                matrix[y * width + x] = 0.0;
        }
    }
    /* pass it to a subroutine */
    using_flat_array_as_2d_array(matrix, width, height);
    system("pause");
    return EXIT_SUCCESS;
}
